package com.cb.web.wasf;

import com.cb.web.wasf.State.StateOrView;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * @author CBO
 */
public abstract class WasfController extends HttpServlet {

    /*@Inject
    private Injector injector;*/
    abstract public State createInitialState();

    /*public Injector getInjector() {
    return injector;
    }*/
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        serve(req, resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        serve(req, resp);
    }

    protected void serve(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {
        //@TODO Multipart request
        //@TODO Error handling
        HttpSession httpSession = httpServletRequest.getSession();
        synchronized (httpSession) {
            processCache(httpServletResponse);
            DefaultSession session = DefaultSession.resolveSession(httpServletRequest);
            State currentState = null;
            if (session.isNew()) {
                currentState = createInitialState();
                session.setCurrentState(currentState);
                DefaultSession.putInRequest(httpServletRequest, session);
                currentState.getView().render(new Response(httpServletRequest, httpServletResponse));
            } else {
                currentState = session.getCurrentState();
                if (session.isUnSynchronized()) {
                    currentState.setRefreshedAfterDesynchronization(true);
                    DefaultSession.putInRequest(httpServletRequest, session);
                    currentState.getView().render(new Response(httpServletRequest, httpServletResponse));
                } else {
                    currentState.setRefreshedAfterDesynchronization(false);
                    StateOrView stateOrView = currentState.handleRequest(new Request(session, httpServletRequest));
                    if (stateOrView.getState() != null) {
                        currentState = stateOrView.getState();
                        if (session.isRequestDestruction()) {
                            session = DefaultSession.newSession(httpServletRequest, session);
                        }
                        session.setCurrentState(currentState);
                        DefaultSession.putInRequest(httpServletRequest, session);
                        currentState.getView().render(new Response(httpServletRequest, httpServletResponse));
                    } else {
                        DefaultSession.putInRequest(httpServletRequest, session);
                        stateOrView.getView().render(new Response(httpServletRequest, httpServletResponse));
                    }
                }
            }
            session.setCurrentState(currentState);
        }
    }

    private void processCache(HttpServletResponse response) {
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache,no-store,max-age=0");
        response.setDateHeader("Expires", 1);
    }
}
